Introduction This month we present a series of assorted date and time routines that illustrate ways to handle dates for business calendar needs. Some are new and a number of others were published in previous issues of TechNotes. We have brought them together to give a more authoritative list of techniques and programs. We hope you find them useful. Setting the System DATE and TIME There is no command in dBASE III or dBASE III PLUS to change the system time and date. To change either or both of them, RUN the DOS programs DATE and TIME. The desired date and time can be placed in a memory variable and passed to the operating system. For example, * ---Set DOS system date. today = "11-01-86" RUN DATE &today * ---Set DOS system time. now = "08:00" RUN TIME &now Excerpted from the March, 1985 issue of TechNotes. Date Formatting To create a custom date display, you can convert a date variable to a formatted string by using SUBSTR(), STR(), and date functions in combination. If, for example, you have a date in and you want the output to look like "January 25, 1984," the expression that makes the conversion is, CMONTH() + " " + STR(DAY(), 2) +; ", " + STR(YEAR(), 4) In this expression, the first portion of the expression, CMONTH() returns the month name as a character string. The second portion of the expression, STR(DAY(), 2) returns the numeric day of the month as a character string. The last portion of the expression, STR(YEAR(), 4) returns the year as a four-character string. The results of this last expression are concatenated to the month and day. This expression can be used as the field contents in a REPORT FORM, a LABEL FORM, or other display command that accepts a character expression such as ? or @...SAY. General Date Formats The following, Fdate.PRG, is a general purpose date formatting procedure. It takes two inputs, a date variable to format and a numeric code designating the format desired, and produces one output, a character variable containing the formatted date string. Call Fdate.PRG with the following general syntax. * ---Receiving variable must exist prior to call. = "" DO Fdate WITH ,; ,; Fdate.PRG supports several date formats. Pick from the following list using the position in the list as the format code parameter when you DO Fdate. 1. Mon DD, YYYY 2. Mon YYYY 3. Mon DD 4. Month DD, YYYY 5. DD-Mon-YYYY Note that the day format for formats 1, 3, and 4, do not include a leading zero. If the day of the month is less than ten, the day will be a single digit number. For format 5, the day format includes a leading zero for a day of the month less than ten. * Program..: Fdate.PRG * Author...: Christopher White * Date.....: November 1, 1986 * published originally January 25, 1985 * Version..: dBASE III PLUS * Note(s)..: This program takes a date variable passed to it * with the PARAMETERS phrase and returns the date * as a formatted character string. * PRIVATE ALL PARAMETERS date, code, datestrg DO CASE CASE code = 1 * ---"Nov 1, 1986" datestrg = SUBSTR(CMONTH(date), 1, 3) + " " +; LTRIM(STR(DAY(date), 2)) + ", " +; STR(YEAR(date), 4) CASE code = 2 * ---"Nov 1986" datestrg = SUBSTR(CMONTH(date), 1, 3) + " " +; STR(YEAR(date), 4) CASE code = 3 * ---"Nov 1" datestrg = SUBSTR(CMONTH(date), 1, 3) + " " +; LTRIM(STR(DAY(date), 2)) CASE code = 4 * ---"November 1, 1986" datestrg = CMONTH(date) + " " +; LTRIM(STR(DAY(date), 2)) + ", " + STR(YEAR(date), 4) CASE code = 5 * ---"01-Nov-1986" datestrg = LEFT(DTOC(date), 2) + "-" +; SUBSTR(CMONTH(date), 1, 3) + "-" +; STR(YEAR(date), 4) OTHERWISE datestrg = "Error" ENDCASE RETURN * EOP Fdate.PRG Excerpted from the March, 1985 issue of TechNotes. Working Days Weekday1 The following two programs, Weekday1.PRG and Weekday2.PRG, show how to account for weekend days when determining a number of working days. Weekday1.PRG allows you to select a start date and a number of days and will provide the number of working days inclusive. To setup Weekday1.PRG or Weekday2.PRG, first CREATE Holiday.DBF with the following structure, Structure for database: Holiday.DBF Field Field Name Type Width Dec 1 Holiday Date 8 Then, APPEND all the holidays that span the range of dates in which you will be working. This means that if you are working with a span of two years, you must have APPENDed two records for each holiday, one for each specific date. To execute Weekday1.PRG, use the following general syntax after initializing a return variable for the number of weekdays. ret_val = "" DO Weekday1 WITH , , ret_val * Program ...: Weekday1.PRG * Author ....: Kenneth N. Getz * Date ......: November 1, 1986 * Version ...: dBASE III PLUS * Note(s) ...: Program to find number of working days given * a starting date and the numbers of days hence. * PRIVATE ALL PARAMETERS start, days, weekdays * ---Get starting date to be a week day. DO WHILE MOD(DOW(start) - 1, 6) = 0 start = start + 1 days = days - 1 ENDDO * ---Subtract weekend days. weekdays = days - INT(days / 7) * 2 * ---Find ending day. endday = DOW(start + days - 1) * ---Subtract for each weekend day. IF MOD(endday - 1, 6) = 0 weekdays = IIF(endday = 1, weekdays - 2, weekdays - 1) ENDIF USE Holiday * ---Data file storing holidays. COUNT TO counter FOR holiday >= start; .AND. holiday <= start + days; .AND. MOD(DOW(holiday) - 1, 6) <> 0 USE * ---Subtract number of holidays. weekdays = weekdays - counter RETURN * EOP Weekday1.PRG Weekday2 Weekday2.PRG is a revision of Weekday1.PRG that allows you to specify a range of dates and returns the number of work days between them. To execute Weekday2.PRG, use the following general syntax after initializing a return variable for the number of work days returned from the routine. ret_val = "" DO Weekday2 WITH , , ret_val * Program ...: Weekday2.PRG * Author ....: Kenneth N. Getz * Date ......: November 1, 1986 (Modified March 16, 1987) * Version ...: dBASE III PLUS * Note(s) ...: Program to find number of working days given * a starting and ending date. Includes both end * dates. * PRIVATE ALL PARAMETERS start, enddate, weekdays days = enddate - start + 1 * ---Get starting date to be a week day. DO WHILE MOD(DOW(start) - 1, 6) = 0 start = start + 1 days = days - 1 ENDDO * ---Get ending date to be a week day. DO WHILE MOD(DOW(enddate) - 1,6) = 0 enddate = enddate - 1 days = days - 1 ENDDO * ---Subtract off weekend days. weekdays = days - INT(days / 7) * 2 USE Holiday COUNT TO counter FOR holiday >= start; .AND. holiday <= start + days; .AND. MOD(DOW(holiday)-1,6) <> 0 USE weekdays = weekdays - counter RETURN * EOP Weekday2.PRG Twelve-Hour Time Format If you find the standard twenty-four--hour clock confusing, you may want to use the following procedure, Ampm.PRG, to display the time in the more familiar twelve-hour format. Ampm.PRG works by using the SUBSTR() function to separate the hours and minutes from the time string you pass. These elements are then converted to the twelve-hour format. To execute Ampm.PRG, use the following general syntax after initializing a return variable, ret_val = "" DO Ampm WITH